﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Farigola.Engine.SystemData.Entity.Type;

namespace Farigola.Engine.SystemData.Entity.inst
{
    /// <summary>
    /// Base class of instance class standard.
    /// The other possible instance class is anonym..
    /// </summary>
    public class EntInstClass : EntInstClassBase
    {
        /**
         * used for data member instance, because there are no link to the type data member.
         * (code/key) Id typeDatamember -> (value) Id instDataMember 
         */
        protected Dictionary<EntityId, EntityId> _dictTypeToInst = new Dictionary<EntityId, EntityId>();

        //=====================================================================
        // Constructors.

        //---------------------------------------------------------------------
        /**
         * constructor.
         * 
         * @param systOrUser
         * @param id
         * @param name
         */
        public EntInstClass(EntityDef.TypeSystOrUser systOrUser, EntTypeClass entTypeClass, EntityId id, String name)
            : base(systOrUser, entTypeClass, id, name)
        {           
        }

        //---------------------------------------------------------------------
        /**
         * constructor.
         * 
         * @param id
         * @param name
         */
        public EntInstClass(EntTypeClass entTypeClass, EntityId id, String name)
            : base(entTypeClass, id, name)
        {            
        }

        //=====================================================================
        // get/set Methods.

        //---------------------------------------------------------------------
        public EntTypeClass getEntTypeClass()
        {
            return (EntTypeClass)_entTypeClassBase;
        }

        //=====================================================================
        // Find methods.

        //---------------------------------------------------------------------
        /**
         * find the type class data member id, by the id of the data member instance.
         * 
         * @param id
         * @return
         */
        public EntityId findTypeClassDataMemberIdByEntInstId(EntityId id)
    {
    	if(id==null)
    		return null;

        foreach (KeyValuePair<EntityId, EntityId> e in _dictTypeToInst)
        {
    		if(id.IdAreEquals(e.Value))
    			return e.Key;
    	}

        return null;
    }

        //=====================================================================
        // Some protected methods.

        //---------------------------------------------------------------------
        /**
         * Find the key by the bvalue in the internal map.
         * key= typeClassDataMember.Id, value= instanceDataMember.Id
         * 
         * @param instDataMemberId
         * @return
         */
        protected EntityId dictFindKeyByValue(EntityId instDataMemberId)
    {
    	if(instDataMemberId==null)
    		return null;

        // Loop over pairs with foreach
    	foreach(KeyValuePair<EntityId, EntityId> e in _dictTypeToInst){
    		if(instDataMemberId.IdAreEquals(e.Value))
    			return e.Key;
    	}

        return null;
    }

        //=====================================================================
        // add/remove data member methods.

        //---------------------------------------------------------------------
        /**
         * Add a new data member to the instance class.
         * Data members of an instance class are build by the factory when the instance class is created.
         * 
         * @param instanceDataMember
         * @param typeDataMember
         * @return
         */
        public bool addEntInstDataMember(EntInstBase instanceDataMember, EntTypeClassDataMember typeDataMember)
        {
            // check if not already present
            if (_listDataMember.Contains(instanceDataMember))
                return false;

            // check if the newName is not already used
            // todo:

            // add an entry in the dict, for inst, to keep a link to the typeClassDataMember
            _dictTypeToInst.Add(typeDataMember.GetId(), instanceDataMember.GetId());

            _listDataMember.Add(instanceDataMember);
            return true;
        }

        //---------------------------------------------------------------------
        /**
         * remove the inst data member from the class.
         * @param instDataMember
         * @return
         */
        public bool removeEntInstClassDataMember(EntInstBase instDataMember)
        {
            if (instDataMember == null)
                return false;

            if (!_listDataMember.Contains(instDataMember))
                return false;

            _listDataMember.Remove(instDataMember);

            // remove from the dict of the instClass!!
            if (!_dictTypeToInst.ContainsValue(instDataMember.GetId()))
                return false;

            EntityId id = dictFindKeyByValue(instDataMember.GetId());
            if (id == null)
                return false;

            _dictTypeToInst.Remove(id);
            return true;
        }
    }
}
